package com.zxp.common.codegen.util;

import cn.hutool.core.io.FileUtil;
import freemarker.cache.FileTemplateLoader;
import freemarker.template.Configuration;
import freemarker.template.Template;
import lombok.extern.slf4j.Slf4j;

import java.io.File;
import java.io.FileWriter;
import java.io.StringReader;
import java.io.StringWriter;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 代码生成器的核心处理类
 *      使用Freemarker完成文件生成
 *             数据模型 + 模板
 *  数据：
 *      数据模型
 *      模板的位置
 *      生成文件的路径
 *
 */
@Slf4j
public class Generator {

    private String templatePath;//模板路径
    private String outPath;//代码生成路径
    private Configuration cfg;//模板加载器配置文件

    public Generator(String templatePath, String outPath) throws Exception {
        this.templatePath = templatePath;
        this.outPath = outPath;
        //实例化Configuration对象
        cfg = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);
        cfg.setDefaultEncoding(Charset.forName("UTF-8").name());
        //指定模板加载器
        FileTemplateLoader ftl = new FileTemplateLoader(new File(templatePath));
        cfg.setTemplateLoader(ftl);
    }

    /**
     * 代码生成
     *      1.扫描模板路径下的所有模板
     *      2.对每个模板进行文件生成（数据模型）
     */
    public void scanAndGenerator(Map<String,Object> dataModel) throws Exception {
        //1.根据模板路径找到此路径下的所有模板文件
        List<File> fileList = FileUtil.loopFiles(new File(templatePath));
        //2.对每个模板进行文件生成
        for (File file : fileList) {
            executeGenerator(dataModel,file);
        }
    }

    /**
     * 对模板进行文件生成
     * @param dataModel ： 数据模型
     * @param file      ： 模板文件
     *            模板文件：c：com.ihrm.system.abc.java
     */
    private void executeGenerator(Map<String,Object> dataModel, File file) throws Exception {
        //1.文件路径处理   (E:\模板\${path1}\${path2}\${path3}\${ClassName}.java)
        //templatePath : E:\模板\
        log.debug(file.getAbsolutePath());
        String templateFileName = file.getAbsolutePath().replace(this.templatePath,"");
        log.debug("模板文件："+templateFileName);
        String outFileName = processTemplateString(templateFileName,dataModel); // 要生成的文件名

        //2.读取文件模板
        Template template = cfg.getTemplate(templateFileName);
        template.setOutputEncoding("utf-8");//指定生成文件的字符集编码
        //3.创建文件
        File file1 = new File(outPath, outFileName);
        if(file1.getParentFile() != null) {
            file1.getParentFile().mkdirs();
        }
        //4.模板处理（文件生成）
        FileWriter fw = new FileWriter(file1);
        template.process(dataModel,fw);
        fw.close();
    }

    /**
     * 字符串模板加载器， 将字符串套用数据模型
     * "\Springboot\${project}\src\main\java\${path1}\${path2}\service\${ClassName}Service.java",变成
     * @param templateString
     * @param dataModel
     * @return
     * @throws Exception
     */
    public String processTemplateString(String templateString,Map dataModel) throws Exception {
        StringWriter out = new StringWriter();
        Template template = new Template("ts",new StringReader(templateString),cfg);
        template.process(dataModel,out);
        String s = out.toString();
        log.debug(templateString+" 路径变换成："+s);
        return s;
    }

    public static void main(String[] args) throws Exception {
        String templatePath = "D:\\JavaDevelop\\IDEAproject\\shizhan\\codeUtils\\模板\\vue的前端界面模板";
        String outPath = "d:\\代码生成目录";
        Generator generator = new Generator(templatePath, outPath);
        Map <String,Object> dataModel = new HashMap<String,Object>();
        dataModel.put("username","张三");
        generator.scanAndGenerator(dataModel);
    }

}
